package org.com.creationalPattern.singleton;

/**
 * 单例模式-饿汉式单例类:类加载时，就进行对象实例化
 * 确保一个类只有一个实例，而且自行实例化并向整个系统提供这个实例。
 * 单例模式的主要作用是确保一个类只有一个实例存在。单例模式可以用在建立目录、
 * 数据库连接等需要单线程操作的场合，用于实现对系统资源的控制。
 * @author Jonny
 * @version 1.0
 * @Description:
 * @date 2021/4/13 15:37
 */
/*
单例模式的优点有以下几个方面
        ■由于单例模式在内存中只有一个实例，减少了内存的开支，特别是一个对象需要频繁地创建、销毁，
            而且创建或销毁的性能又无法优化时，单例模式的优势就非常明显。
        ■ 由于单例模式只生成一个实例，所以减少了系统的性能开销，当一个对象的产生需要比较多资源时，
            如读取配置、产生其他依赖对象时，则可以通过在启用时直接产生一个单例对象，然后用永久驻留内存的方式来解决。
        ■ 单例模式可以避免对资源的多重占用，例如，一个写文件动作，由于只有一个实例存在于内存中，
            避免了对同一个资源文件的同时操作。
        ■ 单例模式可以在系统设置全局的访问点，优化和共享资源访问，例如，可以设计一个单例类，负责所有数据表的映射处理。

单例模式的缺点有以下几个方面
        ■ 单例模式无法创建子类，扩展困难，若要扩展，除了修改代码基本上没有第二种途径可以实现。
        ■ 单例模式对测试不利。在并行开发环境中，如果采用单例模式的类没有完成，是不能进行测试的；
            单例模式的类通常不会实现接口，这也妨碍了使用mock的方式虚拟一个对象。
        ■ 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑，而不关心它是否是单例的，
            是不是要用单例模式取决于环境，单例模式把“要单例”和业务逻辑融合在一起。
            注意单元测试时经常会采用stub和mock方式，这两种方式都可以对系统模块或单元进行隔离，
            通过创建虚拟的对象来模拟真实场景，以便对主要测试对象进行测试工作。
使用场景
在一个系统中，如果要求一个类有且仅有一个实例，当出现多个实例时就会造成不良反应，则此时可以采用单例模式。可以采用单例模式的典型场景如下。
    ■ 要求生成唯一序列号的环境。
    ■ 在整个项目中需要一个共享访问点或共享数据，例如，一个Web页面上的计数器，可以不用把每次刷新都记录到数据库中，
    使用单例模式保持计数器的值，并确保是线程安全的。
    ■ 创建一个对象需要消耗的资源过多，如访问IO和数据库等资源。
    ■ 需要定义大量的静态常量和静态方法（如工具类）的环境，可以采用单例模式（也可以采用直接声明为static的方式）。
    单例模式是23个模式中比较简单的模式，应用也非常广泛，如在Spring框架中，每个Bean 默认就是单例的；
    Java 基础类库中的 java.lang.Runtime 类也采用了单例模式，其getRuntime()方法返回了唯一的实例。

注意事项
    使用单例模式的注意事项根据功能，单例类可以分为有状态单例类和无状态单例类。
    ■ 有状态单例类：一个有状态单例类的对象一般是可变的，通常当做状态库使用。例如，给系统提供一个唯一的序列号。
    ■ 无状态单例类：无状态单例类是不变的，通常用来提供工具性的功能方法。例如， IO或数据库访问等。因为单例类具有状态，
    所以在使用时应注意以下两点。
    ■ 单例类仅局限于一个JVM，因此当多个JVM的分布式系统时，这个单例类就会在多个JVM中被实例化，造成多个单例对象的出现。
    如果是无状态的单例类，则没有问题，因为这些单例对象是没有区别的。如果是有状态的单例类，则会出现问题，例如，给系统提供一个唯一的序列号，
    此时序列号不唯一，可能出现多次。因此，在任何使用EJB、RMI和JINI技术的分布式系统中，应当避免使用有状态的单例类。
    ■ 同一个JVM中会有多个类加载器，当两个类加载器同时加载同一个类时，会出现两个实例，此时也应尽量避免使用有状态的单例类。

    另外，使用单例模式时，需要注意序列化和克隆对实例唯一性的影响。如果一个单例的类实现了Serializable或Cloneable接口，
    则有可能被反序列化或克隆出一个新的实例来，从而破坏了“唯一实例”的要求，因此，通常单例类不需要实现Serializable和Cloneable接口

 */
public class Singleton {
    private static Singleton _singlenton=new Singleton();

    public Singleton(){

    }
    public static Singleton getInstance(){
        return _singlenton;
    }
}
